home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / macabuse / src / light.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-05-20  |  33.1 KB  |  1,371 lines

  1. #include "light.hpp"
  2. #include <stdlib.h>
  3. #include "image.hpp"
  4. #include "macs.hpp"
  5. #include "video.hpp"
  6. #include "palette.hpp"
  7. #include "timing.hpp"
  8. #include "specs.hpp"
  9. #include "dprint.hpp"
  10. #include "filter.hpp"
  11. #include "status.hpp"
  12. #include "dev.hpp"
  13.  
  14. light_source *first_light_source=NULL;
  15. unsigned char *white_light,*white_light_initial,*green_light,*trans_table;
  16. short ambient_ramp=0;
  17. short shutdown_lighting_value,shutdown_lighting=0;
  18. extern char disable_autolight;   // defined in dev.hpp
  19.  
  20. #ifdef MAC_PROFILE
  21. unsigned lighting_loop_time;
  22.  
  23. extern char kjfie[][256];  // kill me
  24. int loopnum1,loopnum2,tmp; //kill me
  25.  
  26. extern long StartTime(int cnt);         //kill me
  27. extern long DiffTime(char *name, int cnt);   //kill me
  28. #else
  29. inline long StartTime(int cnt) { return 0; }         //kill me
  30. inline long DiffTime(char *name, int cnt) { return 0; }  //kill me
  31. #endif
  32.  
  33. int light_detail=MEDIUM_DETAIL;
  34.  
  35. long light_to_number(light_source *l)
  36. {
  37.   
  38.   if (!l) return 0;
  39.   int x=1;
  40.   for (light_source *s=first_light_source;s;s=s->next,x++)
  41.     if (s==l) return x;
  42.   return 0;
  43. }
  44.  
  45.  
  46. light_source *number_to_light(long x)
  47. {
  48.   if (x==0) return NULL;
  49.   x--;
  50.   light_source *s=first_light_source;
  51.   for (;x && s;x--,s=s->next);
  52.   return s;       
  53. }
  54.  
  55. light_source *light_source::copy()
  56. {
  57.   next=new light_source(type,x,y,inner_radius,outer_radius,xshift,yshift,next);
  58.   return next;
  59. }
  60.  
  61. void delete_all_lights()
  62. {
  63.   while (first_light_source)
  64.   {
  65.     if (dev_cont)
  66.       dev_cont->notify_deleted_light(first_light_source);
  67.  
  68.     light_source *p=first_light_source;
  69.     first_light_source=first_light_source->next;
  70.     delete p;
  71.   }
  72. }
  73.  
  74. void delete_light(light_source *which)
  75. {
  76.   if (dev_cont)
  77.     dev_cont->notify_deleted_light(which);
  78.  
  79.   if (which==first_light_source)
  80.   {
  81.     first_light_source=first_light_source->next;
  82.     delete which;
  83.   }
  84.   else
  85.   {
  86.     light_source *f=first_light_source;
  87.     for (;f->next!=which && f;f=f->next);
  88.     if (f)
  89.     {
  90.       f->next=which->next;
  91.       delete which;
  92.     }
  93.   }
  94. }
  95.  
  96. void light_source::calc_range()
  97. {
  98.   switch (type)
  99.   {
  100.     case 0 :
  101.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  102.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  103.     } break;
  104.     case 1 :
  105.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  106.       x2=x+(outer_radius>>xshift); y2=y;
  107.     } break;
  108.     case 2 :
  109.     { x1=x-(outer_radius>>xshift); y1=y;
  110.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  111.     } break;
  112.     case 3 :
  113.     { x1=x; y1=y-(outer_radius>>yshift);
  114.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  115.     } break;
  116.     case 4 :
  117.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  118.       x2=x; y2=y+(outer_radius>>yshift);
  119.     } break;
  120.  
  121.  
  122.     case 5 :
  123.     { x1=x; y1=y-(outer_radius>>yshift);
  124.       x2=x+(outer_radius>>xshift); y2=y;
  125.     } break;
  126.     case 6 :
  127.     { x1=x-(outer_radius>>xshift); y1=y-(outer_radius>>yshift);
  128.       x2=x; y2=y;
  129.     } break;
  130.     case 7 :
  131.     { x1=x-(outer_radius>>xshift); y1=y;
  132.       x2=x; y2=y+(outer_radius>>yshift);
  133.     } break;
  134.     case 8 :
  135.     { x1=x; y1=y;
  136.       x2=x+(outer_radius>>xshift); y2=y+(outer_radius>>yshift);
  137.     } break;
  138.     case 9 :
  139.     {
  140.       x1=x;
  141.       y1=y;
  142.       x2=x+xshift;
  143.       y2=y+yshift;
  144.     } break;
  145.  
  146.   }
  147.   mul_div=(1<<16)/(outer_radius-inner_radius)*64;
  148. }
  149.  
  150. light_source::light_source(char Type, long X, long Y, long Inner_radius, 
  151.                long Outer_radius, long Xshift,  long Yshift, light_source *Next)
  152.   type=Type; 
  153.   x=X; y=Y; 
  154.   inner_radius=Inner_radius;  
  155.   outer_radius=Outer_radius; 
  156.   next=Next; 
  157.   known=0;
  158.   xshift=Xshift;
  159.   yshift=Yshift;
  160.   calc_range(); 
  161. }
  162.  
  163.  
  164. int count_lights()
  165. {
  166.   int t=0;
  167.   for (light_source *s=first_light_source;s;s=s->next)
  168.     t++;
  169.   return t;
  170. }
  171.  
  172. light_source *add_light_source(char type, long x, long y, 
  173.                    long inner, long outer, long xshift, long yshift)
  174. {
  175.   first_light_source=new light_source(type,x,y,inner,outer,xshift,yshift,first_light_source);
  176.   return first_light_source;
  177. }
  178.  
  179.  
  180. #define TTINTS 9
  181. uchar *tints[TTINTS];
  182. uchar bright_tint[256];
  183.  
  184. void calc_tint(uchar *tint, int rs, int gs, int bs, int ra, int ga, int ba, palette *pal)
  185. {
  186.   palette npal;
  187.   memset(npal.addr(),0,256);
  188.   int i=0;
  189.   for (;i<256;i++)
  190.   {
  191.     npal.set(i,(int)rs,(int)gs,(int)bs);
  192.     rs+=ra; if (rs>255) rs=255; if (rs<0) rs=0;
  193.     gs+=ga; if (gs>255) gs=255; if (gs<0) gs=0;
  194.     bs+=ba; if (bs>255) bs=255; if (bs<0) bs=0;
  195.   }
  196.   filter f(pal,&npal);
  197.   filter f2(&npal,pal);
  198.  
  199.   for (i=0;i<256;i++,tint++)
  200.     *tint=f2.get_mapping(f.get_mapping(i));
  201. }
  202.  
  203.  
  204. void calc_light_table(palette *pal)
  205. {
  206.   
  207.   white_light_initial=(unsigned char *)jmalloc(256*64+256,"light table");
  208.   
  209.   // align memory to 256 byte boundary
  210.   white_light= (unsigned char*)((((unsigned long)white_light_initial) + 255)&~0xff);
  211.  
  212. //  green_light=(unsigned char *)jmalloc(256*64,"green light");
  213.   int i=0;
  214.   for (;i<TTINTS;i++)
  215.       tints[i]=(uchar *)jmalloc(256,"color tint");
  216.  
  217.   bFILE *fp=open_file("light.tbl","rb");
  218.   int recalc=0;
  219.   if (fp->open_failure()) 
  220.   {
  221.     recalc=1;
  222.     delete fp;
  223.   }
  224.   else
  225.   {
  226.     if (fp->read_short()!=calc_crc((unsigned char *)pal->addr(),768))
  227.       recalc=1;
  228.     else
  229.     {
  230.       fp->read(white_light,256*64);
  231. //      fp->read(green_light,256*64);
  232.       for (i=0;i<TTINTS;i++)
  233.         fp->read(tints[i],256);
  234.       fp->read(bright_tint,256);
  235. //      trans_table=(uchar *)jmalloc(256*256,"transparency table");
  236. //      fp.read(trans_table,256*256);
  237.     }
  238.     delete fp;
  239.   }
  240.  
  241.   if (recalc)
  242.   {  
  243.     dprintf("Palette has changed, recalculating light table...\n");
  244.     stat_man->push("white light",NULL);
  245.     int color=0;
  246.     for (;color<256;color++)
  247.     {
  248.       unsigned char r,g,b;
  249.       pal->get(color,r,g,b);
  250.       stat_man->update(color*100/256);
  251.       for (int intensity=63;intensity>=0;intensity--)
  252.       {
  253.     if (r>0 || g>0 || b>0)
  254.           white_light[intensity*256+color]=pal->find_closest(r,g,b);
  255.     else
  256.           white_light[intensity*256+color]=0;
  257.     if (r) r--;  if (g) g--;  if (b) b--;     
  258.       } 
  259.  
  260.  
  261.  
  262.     }
  263.     stat_man->pop();
  264.  
  265. /*    stat_man->push("green light",NULL);
  266.     for (color=0;color<256;color++)
  267.     {
  268.       stat_man->update(color*100/256);
  269.       unsigned char r,g,b;
  270.       pal->get(color,b,r,g);
  271.       r=r*3/5; b=b*3/5; g+=7; if (g>255) g=255;
  272.  
  273.       for (int intensity=63;intensity>=0;intensity--)
  274.       {
  275.     if (r>0 || g>0 || b>0)
  276.           green_light[intensity*256+color]=pal->find_closest(r,g,b);
  277.     else
  278.           green_light[intensity*256+color]=0;
  279.     if (r) r--;  
  280.     if ((intensity&1)==1)
  281.       if (g) g--;  
  282.     if (b) b--;
  283.       }
  284.     }
  285.     stat_man->pop(); */
  286.  
  287.     stat_man->push("tints",NULL);
  288.     uchar t[TTINTS*6]={0,0,0,0,0,0, // normal
  289.                    0,0,0,1,0,0,     // red
  290.            0,0,0,1,1,0,     // yellow
  291.            0,0,0,1,0,1,     // purple
  292.            0,0,0,1,1,1,     // gray
  293.            0,0,0,0,1,0,     // green
  294.            0,0,0,0,0,1,     // blue
  295.            0,0,0,0,1,1,     // cyan 
  296.  
  297.  
  298.  
  299.  
  300.  
  301.  
  302.            0,0,0,0,0,0   // reverse green  (night vision effect)
  303.          } ;
  304.     uchar *ti=t+6;
  305.     uchar *c;
  306.     for (i=0,c=tints[0];i<256;i++,c++) *c=i;  // make the normal tint (maps everthing to itself)
  307.     for (i=0,c=tints[TTINTS-1];i<256;i++,c++)  // reverse green
  308.     {
  309.       int r=pal->red(i)/2,g=255-pal->green(i)-30,b=pal->blue(i)*3/5+50;
  310.       if (g<0) g=0;
  311.       if (b>255) b=0;
  312.       *c=pal->find_closest(r,g,b);
  313.     }
  314.     for (i=0;i<256;i++)
  315.     {
  316.       int r=pal->red(i)+(255-pal->red(i))/2,
  317.           g=pal->green(i)+(255-pal->green(i))/2,
  318.           b=pal->blue(i)+(255-pal->blue(i))/2;
  319.       bright_tint[i]=pal->find_closest(r,g,b);
  320.     }
  321.  
  322.     // make the colored tints
  323.     for (i=1;i<TTINTS-1;i++)
  324.     {
  325.       stat_man->update(i*100/(TTINTS-1));
  326.       calc_tint(tints[i],ti[0],ti[1],ti[2],ti[3],ti[4],ti[5],pal);
  327.       ti+=6;
  328.     }
  329.     stat_man->pop();
  330. /*    dprintf("calculating transparency tables (256 total)\n");
  331.     trans_table=(uchar *)jmalloc(256*256,"transparency table");
  332.  
  333.     uchar *tp=trans_table;
  334.     for (i=0;i<256;i++)
  335.     {      
  336.       uchar r1,g1,b1,r2,g2,b2;
  337.       pal->get(i,r1,g1,b1);
  338.       if ((i%16)==0)
  339.         dprintf("%d ",i);
  340.       for (int j=0;j<256;j++,tp++)
  341.       {
  342.     if (r1==0 && r2==0 && b2==0)
  343.       *tp=j;
  344.     else
  345.     {
  346.       pal->get(j,r2,g2,b2);       
  347.       *tp=pal->find_closest((r2-r1)*3/7+r1,(g2-g1)*3/7+g1,(b2-b1)*3/7+b1);
  348.     }
  349.       }
  350.     }*/
  351.  
  352.  
  353.     bFILE *f=open_file("light.tbl","wb");
  354.     if (f->open_failure())    
  355.       dprintf("Unable to open file light.tbl for writing\n");
  356.     else
  357.     {
  358.       f->write_short(calc_crc((unsigned char *)pal->addr(),768));
  359.       f->write(white_light,256*64);
  360. //      f->write(green_light,256*64);
  361.       for (int i=0;i<TTINTS;i++)
  362.         f->write(tints[i],256);
  363.       fp->write(bright_tint,256);
  364. //    f.write(trans_table,256*256);
  365.     }
  366.     delete f;
  367.   }
  368. }
  369.  
  370.  
  371. light_patch *light_patch::copy(light_patch *Next)
  372.   light_patch *p=new light_patch(x1,y1,x2,y2,Next); 
  373.   p->total=total;
  374.   if (total)    
  375.   {
  376.     p->lights=(light_source **)jmalloc(total*sizeof(light_source *),"light patches");
  377.     memcpy(p->lights,lights,total*(sizeof(light_source *)));
  378.   }
  379.   else 
  380.     p->lights=NULL; 
  381.   return p;
  382. }
  383.  
  384. #define MAX_LP 6
  385.  
  386. // insert light into list make sure the are sorted by y1
  387. void insert_light(light_patch *&first, light_patch *l)
  388. {
  389.   if (!first)
  390.     first=l;
  391.   else if (l->y1<first->y1)
  392.   {
  393.     l->next=first;
  394.     first=l;
  395.   } else
  396.   {
  397.     light_patch *p=first;
  398.     for (;p->next && p->next->y1<l->y1;p=p->next);
  399.     l->next=p->next;
  400.     p->next=l;
  401.   }
  402. }
  403.  
  404. void add_light(light_patch *&first, long x1, long y1, long x2, long y2, 
  405.                 light_source *who)
  406. {  
  407.   light_patch *last=NULL,*next;
  408.   light_patch *p=first;
  409.   for (;p;p=next)
  410.   {
  411.     next=p->next;
  412.     // first see if light patch we are adding is enclosed entirely by another patch
  413.     if (x1>=p->x1 && y1>=p->y1 && x2<=p->x2 && y2<=p->y2)
  414.     {
  415.       if (p->total==MAX_LP) return ;
  416.  
  417.       if (x1>p->x1)
  418.       {
  419.     light_patch *l=p->copy(NULL);
  420.     l->x2=x1-1;
  421.     insert_light(first,l);
  422.       }
  423.       if (x2<p->x2)
  424.       {
  425.     light_patch *l=p->copy(NULL);
  426.     l->x1=x2+1;
  427.     insert_light(first,l);
  428.       }
  429.       if (y1>p->y1)
  430.       {
  431.     light_patch *l=p->copy(NULL);
  432.     l->x1=x1;
  433.     l->x2=x2;
  434.     l->y2=y1-1;
  435.     insert_light(first,l);
  436.       }
  437.       if (y2<p->y2)
  438.       {
  439.     light_patch *l=p->copy(NULL);
  440.     l->x1=x1;
  441.     l->x2=x2;
  442.     l->y1=y2+1;
  443.     insert_light(first,l);
  444.       }
  445.       p->x1=x1; p->y1=y1; p->x2=x2; p->y2=y2;
  446.       // p has possibly changed it's y1, so we need to move it to it's correct sorted 
  447.       // spot in the list
  448.       if (first==p)
  449.         first=first->next;
  450.       else
  451.       {
  452.     light_patch *q=first;
  453.     for (;q->next!=p;q=q->next);
  454.     q->next=p->next;
  455.       }
  456.       insert_light(first,p);
  457.       
  458.  
  459.       p->total++;     
  460.       p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
  461.       p->lights[p->total-1]=who;
  462.       return ;
  463.     }
  464.  
  465.     // see if the patch completly covers another patch.
  466.     if (x1<=p->x1 && y1<=p->y1 && x2>=p->x2 && y2>=p->y2)
  467.     {
  468.       if (x1<p->x1)
  469.         add_light(first,x1,y1,p->x1-1,y2,who);
  470.       if (x2>p->x2)
  471.         add_light(first,p->x2+1,y1,x2,y2,who);
  472.       if (y1<p->y1)
  473.         add_light(first,p->x1,y1,p->x2,p->y1-1,who);
  474.       if (y2>p->y2)
  475.         add_light(first,p->x1,p->y2+1,p->x2,y2,who);
  476.       if (p->total==MAX_LP)  return ;
  477.       p->total++;     
  478.       p->lights=(light_source **)jrealloc(p->lights,sizeof(light_source *)*p->total,"patch_list");
  479.       p->lights[p->total-1]=who;
  480.       return ;
  481.     }
  482.  
  483.     // see if we intersect another rect
  484.     if (!(x2<p->x1 || y2<p->y1 || x1>p->x2 || y1>p->y2))  
  485.     {
  486.       int ax1,ay1,ax2,ay2;
  487.       if (x1<p->x1)
  488.       {
  489.         add_light(first,x1,max(y1,p->y1),p->x1-1,min(y2,p->y2),who);
  490.     ax1=p->x1;
  491.       } else
  492.     ax1=x1;
  493.  
  494.       if (x2>p->x2)
  495.       {
  496.         add_light(first,p->x2+1,max(y1,p->y1),x2,min(y2,p->y2),who);
  497.     ax2=p->x2;
  498.       } 
  499.       else
  500.     ax2=x2;
  501.  
  502.       if (y1<p->y1)
  503.       {       
  504.         add_light(first,x1,y1,x2,p->y1-1,who);
  505.     ay1=p->y1;
  506.       } else 
  507.     ay1=y1;
  508.  
  509.       if (y2>p->y2)
  510.       {
  511.         add_light(first,x1,p->y2+1,x2,y2,who);
  512.     ay2=p->y2;
  513.       } else 
  514.     ay2=y2;
  515.  
  516.        
  517.       add_light(first,ax1,ay1,ax2,ay2,who);      
  518.  
  519.       return ;    
  520.     }
  521.   }
  522. }
  523.  
  524. light_patch *find_patch(int screenx, int screeny, light_patch *list)
  525. {
  526.   for (;list;list=list->next)
  527.   {
  528.     if (screenx>=list->x1 && screenx<=list->x2 && screeny>=list->y1 && screeny<=list->y2)
  529.       return list;
  530.   }
  531.   return NULL;
  532. }
  533.  
  534. /* shit
  535. int calc_light_value(light_patch *which, long x, long y)
  536. {
  537.   int lv=0;
  538.   int t=which->total;
  539.   for (register int i=t-1;i>=0;i--)
  540.   {    
  541.     light_source *fn=which->lights[i];
  542.     if (fn->type==9)
  543.     {
  544.       lv=fn->inner_radius;
  545.       i=0;
  546.     }
  547.     else
  548.     {
  549.       long dx=abs(fn->x-x)<<fn->xshift;
  550.       long dy=abs(fn->y-y)<<fn->yshift;
  551.       long  r2;
  552.       if (dx<dy)
  553.         r2=dx+dy-(dx>>1);
  554.       else r2=dx+dy-(dy>>1);
  555.     
  556.       if (r2>=fn->inner_radius)
  557.       {
  558.     if (r2<fn->outer_radius)
  559.     {
  560.       lv+=((fn->outer_radius-r2)*fn->mul_div)>>16;
  561.     }
  562.       } else lv=63;      
  563.     }
  564.   }
  565.   if (lv>63) return 63; 
  566.   else
  567.     return lv;
  568. } */
  569.  
  570.  
  571. void reduce_patches(light_patch *f)   // find constant valued patches
  572. {
  573.   
  574. }
  575.  
  576. light_patch *make_patch_list(int width, int height, long screenx, long screeny)
  577. {
  578.   light_patch *first=new light_patch(0,0,width-1,height-1,NULL);
  579.  
  580.   for (light_source *f=first_light_source;f;f=f->next)   // determine which lights will have effect
  581.   {
  582.     long x1=f->x1-screenx,y1=f->y1-screeny,
  583.         x2=f->x2-screenx,y2=f->y2-screeny;
  584.     if (x1<0) x1=0;
  585.     if (y1<0) y1=0;
  586.     if (x2>=width)  x2=width-1;
  587.     if (y2>=height) y2=height-1;
  588.  
  589.     if (x1<=x2 && y1<=y2)
  590.       add_light(first,x1,y1,x2,y2,f);
  591.   }
  592.   reduce_patches(first);
  593.  
  594.   return first;
  595. }
  596.  
  597.  
  598. void delete_patch_list(light_patch *first)
  599. {
  600.   while (first)
  601.   {
  602.     light_patch *p=first;
  603.     first=first->next;
  604.     delete p;
  605.   }
  606. }
  607.  
  608. /*
  609. #ifdef __WATCOMC__
  610. extern "C" {
  611. extern long MAP_PUT(long pad, long screen_addr, long remap, long w);
  612. } ;
  613. #else*/
  614.  
  615. inline void MAP_PUT(long screen_addr, long remap, long w)
  616.   register int cx=w;
  617.   register int di=screen_addr;
  618.   register int si=remap;
  619.   while (cx--) 
  620.     *((uchar *)(di++))=*((uchar *)si+*((uchar *)di)); 
  621. }
  622.  
  623. inline void MAP_2PUT(long in_addr, long out_addr, long remap, long w)
  624.   while (w--) 
  625.   {
  626.     uchar x=*(((uchar *)remap)+(*(uchar *)(in_addr++)));
  627.     *((uchar *)(out_addr++))=x;
  628.     *((uchar *)(out_addr++))=x;
  629.   }
  630. }
  631.  
  632. /*
  633. #endif
  634.  
  635. inline void PUT8(long *addr, uchar *remap)
  636. {
  637.   register ulong in_pixels;
  638.   register ulong pixel;
  639.   register ulong out_pixels;
  640.   in_pixels=*addr;
  641.   pixel=in_pixels;
  642.   out_pixels=remap[(uchar)pixel];
  643.   
  644.   pixel=in_pixels;
  645.   pixel>>=8;
  646.   pixel=remap[(uchar)pixel];
  647.   pixel<<=8;
  648.   out_pixels|=pixel;
  649.  
  650.   pixel=in_pixels;
  651.   pixel>>=16;
  652.   pixel=remap[(uchar)pixel];
  653.   pixel<<=16;
  654.   out_pixels|=pixel;
  655.  
  656.   pixel=in_pixels;
  657.   pixel>>=24;
  658.   pixel=remap[(uchar)pixel];
  659.   pixel<<=24;
  660.   out_pixels|=pixel;
  661.  
  662.   *addr=out_pixels;        // send out bus
  663.  
  664.   // do next 4
  665.   in_pixels=addr[1];
  666.  
  667.   pixel=in_pixels;
  668.   pixel&=0xff;
  669.   out_pixels=remap[pixel];
  670.   
  671.   pixel=in_pixels;
  672.   pixel>>=8;
  673.   pixel=remap[(uchar)pixel];
  674.   pixel<<=8;
  675.   out_pixels|=pixel;
  676.  
  677.   pixel=in_pixels;
  678.   pixel>>=16;
  679.   pixel=remap[(uchar)pixel];
  680.   pixel<<=16;
  681.   out_pixels|=pixel;
  682.  
  683.   pixel=in_pixels;
  684.   pixel>>=24;
  685.   pixel=remap[(uchar)pixel];
  686.   pixel<<=24;
  687.   out_pixels|=pixel;  
  688.   addr[1]=out_pixels;        // send out bus
  689.   
  690. }
  691.  
  692. inline long MAP_PUT2(long dest_addr, long screen_addr, long remap, long w)
  693. { while (w--) 
  694.   { 
  695.     *((uchar *)(dest_addr))=*((uchar *)remap+*((uchar *)screen_addr)); 
  696.     screen_addr++; 
  697.     dest_addr++;
  698.   } 
  699.   return dest_addr;
  700. }
  701.  
  702. */
  703.  
  704. ushort min_light_level;
  705. // calculate the light value for this block.  sum up all contritors
  706. inline int calc_light_value(light_patch *lp,   // light patch to look at
  707.                 long sx,           // screen x & y
  708.                 long sy)
  709. {
  710.   int lv=min_light_level,r2,light_count;
  711.   register int dx,dy;           // x and y distances
  712.  
  713.   light_source **lon_p=lp->lights;
  714.  
  715.   for (light_count=lp->total;light_count>0;light_count--)
  716.   {
  717.     light_source *fn=*lon_p;
  718.     register long *dt=&(*lon_p)->type; 
  719.                                      // note we are accessing structure members by bypassing the compiler
  720.                                      // for speed, this may not work on all compilers, but don't
  721.                                      // see why it shouldn't..  all members are long
  722.     
  723.     if (*dt==9)                      // (dt==type),  if light is a Solid rectangle, return it value
  724.       return fn->inner_radius;
  725.     else
  726.     {
  727.       dt++;
  728.       dx=abs(*dt-sx); dt++;               // xdist between light and this block  (dt==x)
  729.       dx<<=*dt;  dt++;                    // shift makes distance further, 
  730.                                           // making light skinner. (dt==xshift)
  731.  
  732.       dy=abs(*dt-sy); dt++;                   // ydist (dt==y)
  733.       dy<<=*dt;  dt++;                        // (dt==yshift)
  734.  
  735.       if (dx<dy)                     // calculate approximate distance
  736.         r2=dx+dy-(dx>>1);
  737.       else r2=dx+dy-(dy>>1);
  738.       
  739.       if (r2<*dt)                    // if this withing the light's outer radius?  (dt==outer_radius)
  740.       {        
  741.     int v=*dt-r2; dt++;        
  742.     lv+=v*(*dt)>>16;
  743.       }
  744.     }
  745.     lon_p++;
  746.   }
  747.  
  748.   if (lv>63) 
  749.     return 63;          // lighting table only has 64 (256 bytes) entries 
  750.   else return lv;
  751. }
  752.  
  753.  
  754. /*#ifdef __WATCOMC__
  755.  
  756. extern "C" void remap_line_asm(uchar *screen_line,uchar *light_lookup,uchar *remap_line,int count);
  757.  
  758. #else */
  759.  
  760. #if 0
  761. //defined( __MAC__ ) && defined( __POWERPC__ )
  762. asm void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
  763. //inline void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
  764. {
  765.     stmw        r17, -60(SP)
  766.     // r3 = addr
  767.     // r4 = light_lookup
  768.     // r5 = remap_line
  769.     // r6 = count
  770.     addic        r5, r5, -1                        // remap_line--
  771.     lwz            r18, 0(r3)
  772.     lwzu        r17, 4(r3)
  773.     addic.    r6, r6, 0
  774.     b                remap_end_loop
  775.     
  776. remap_loop:
  777.     mr            r30, r4
  778.     lbzu        r31, 1(r5)                        // remap_line++ ; r31 = *remap_line
  779.     rlwimi    r31, r31, 8, 0, 31        // r31 = *remap_line << 8
  780.     add            r30, r30, r31                    // r30 = light_lookup + (*remap_line << 8)
  781.     mr            r23, r30
  782.  
  783.     mr            r29, r18
  784.     mr            r28, r17
  785.     
  786.     lwzu        r18, 4(r3)                        // addr+=4 ; r29 = *(long*)addr
  787.     lwzu        r17, 4(r3)                        // addr+=4 ; r28 = *(long*)addr
  788.  
  789.     rlwimi    r30, r29, 0, 24, 31        // r30 = light_lookup + (*remap_line << 8) + addr[3]
  790.     rlwimi    r23, r28, 0, 24, 31        // r23 = light_lookup + (*remap_line << 8) + addr[7]
  791.     lbz            r27, 0(r30)                        // r27 = (r30)
  792.     lbz            r22, 0(r23)                        // r22 = (r23)
  793.     rlwimi    r30, r29, 8, 24, 31        // r30 = light_lookup + (*remap_line << 8) + addr[0]
  794.     rlwimi    r23, r28, 8, 24, 31        // r23 = light_lookup + (*remap_line << 8) + addr[4]
  795.     lbz            r26, 0(r30)                        // r26 = (r30)
  796.     lbz            r21, 0(r23)                        // r21 = (r23)
  797.     rlwimi    r30, r29, 16, 24, 31    // r30 = light_lookup + (*remap_line << 8) + addr[1]
  798.     rlwimi    r23, r28, 16, 24, 31    // r23 = light_lookup + (*remap_line << 8) + addr[5]
  799.     rlwimi    r27, r26, 24, 0, 7
  800.     rlwimi    r22, r21, 24, 0, 7
  801.     lbz            r25, 0(r30)                        // r25 = (r30)
  802.     lbz            r20, 0(r23)                        // r20 = (r23)
  803.     rlwimi    r30, r29, 24, 24, 31    // r30 = light_lookup + (*remap_line << 8) + addr[2]
  804.     rlwimi    r23, r28, 24, 24, 31    // r23 = light_lookup + (*remap_line << 8) + addr[6]
  805.     rlwimi    r27, r25, 16, 8, 15
  806.     rlwimi    r22, r20, 16, 8, 15
  807.     lbz            r24, 0(r30)                        // r24 = (r30)
  808.     lbz            r19, 0(r23)                        // r19 = (r23)
  809.     rlwimi    r27, r24, 8, 16, 23
  810.     rlwimi    r22, r19, 8, 16, 23
  811.  
  812.     stw            r27, -12(r3)
  813.     stw            r22, -8(r3)
  814.  
  815.     addic.    r6, r6, -1
  816. remap_end_loop:
  817.     bgt            remap_loop
  818.     nop
  819.  
  820.     lmw            r17, -60(SP)
  821.     blr
  822.     
  823. }
  824. #else
  825. void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
  826. //inline void remap_line_asm2(uchar *addr,uchar *light_lookup,uchar *remap_line,int count)
  827. {
  828.   while (count--)
  829.   {
  830.     uchar *off=light_lookup+(((long)*remap_line)<<8); 
  831.     remap_line++;
  832.  
  833.     *addr=off[*addr]; 
  834.     addr[1]=off[addr[1]];
  835.     addr[2]=off[addr[2]];
  836.     addr[3]=off[addr[3]];
  837.     addr[4]=off[addr[4]];
  838.     addr[5]=off[addr[5]];
  839.     addr[6]=off[addr[6]];
  840.     addr[7]=off[addr[7]];
  841.     addr+=8;
  842.  
  843.   }
  844. }
  845. #endif
  846.  
  847. //#endif
  848.  
  849.  
  850. inline void put_8line(uchar *in_line, uchar *out_line, uchar *remap, uchar *light_lookup, int count)
  851. {
  852.   uchar v;
  853.   int x;
  854.   for (x=0;x<count;x++)                        
  855.   {                                            
  856.     uchar *off=light_lookup+(((long)*remap)<<8);
  857.  
  858.     v=off[*(in_line++)];
  859.     *(out_line++)=v;
  860.     *(out_line++)=v;
  861.  
  862.     v=off[*(in_line++)];
  863.     *(out_line++)=v;
  864.     *(out_line++)=v;
  865.  
  866.     v=off[*(in_line++)];
  867.     *(out_line++)=v;
  868.     *(out_line++)=v;
  869.  
  870.     v=off[*(in_line++)];
  871.     *(out_line++)=v;
  872.     *(out_line++)=v;
  873.  
  874.     v=off[*(in_line++)];
  875.     *(out_line++)=v;
  876.     *(out_line++)=v;
  877.  
  878.     v=off[*(in_line++)];
  879.     *(out_line++)=v;
  880.     *(out_line++)=v;
  881.  
  882.     v=off[*(in_line++)];
  883.     *(out_line++)=v;
  884.     *(out_line++)=v;
  885.  
  886.     v=off[*(in_line++)];
  887.     *(out_line++)=v;
  888.     *(out_line++)=v;
  889.  
  890.     remap++;
  891.   }
  892. }
  893.  
  894.  
  895. void light_screen(image *sc, long screenx, long screeny, uchar *light_lookup, ushort ambient)
  896. {
  897.   int lx_run,ly_run;                     // light block x & y run size in pixels ==  (1<<lx_run)
  898.  
  899. #if defined( __MAC__ ) && !defined( __POWERPC__ )
  900.     return;
  901. #endif
  902.  
  903.     StartTime(14); //kill me
  904.   if (shutdown_lighting && !disable_autolight)
  905.     ambient=shutdown_lighting_value;
  906.  
  907.   switch (light_detail) 
  908.   {
  909.     case HIGH_DETAIL : 
  910.     { lx_run=2; ly_run=1; } break;       // 4 x 2 patches
  911.     case MEDIUM_DETAIL :
  912.     { lx_run=3; ly_run=2; } break;       // 8 x 4 patches  (default)
  913.     case LOW_DETAIL :
  914.     { lx_run=4; ly_run=3; } break;       // 16 x 8 patches
  915.     case POOR_DETAIL :                   // poor detail is no lighting
  916.     return ;
  917.   }
  918.   if ((int)ambient+ambient_ramp<0)
  919.     min_light_level=0;
  920.   else if ((int)ambient+ambient_ramp>63)
  921.     min_light_level=63;
  922.   else min_light_level=(int)ambient+ambient_ramp;
  923.  
  924.   if (ambient==63) return ;
  925.   short cx1,cy1,cx2,cy2;
  926.   sc->get_clip(cx1,cy1,cx2,cy2);
  927.  
  928.   unsigned char *mint=light_lookup+min_light_level*256;
  929.  
  930.   light_patch *first=make_patch_list(cx2-cx1+1,cy2-cy1+1,screenx,screeny);
  931.  
  932.  
  933.   int ytry=(1<<ly_run),xtry=(1<<lx_run);
  934.   int calcx_mask=(0xefffffff-(xtry-1));
  935.   int calcy_mask=(0xefffffff-(ytry-1));
  936.   int scr_w=screen->width();
  937.  
  938.  
  939.   int prefix_x=(screenx&7);
  940.   int prefix=screenx&7;
  941.   if (prefix)
  942.     prefix=8-prefix;
  943.   int suffix_x=cx2-cx1-(screenx&7);
  944.  
  945.   int inside_xoff=(screenx+7)&(~7);
  946.  
  947.   int suffix=(cx2-cx1-prefix+1)&7;
  948.  
  949.  
  950.   long remap_size=((cx2-cx1+1-prefix-suffix)>>lx_run);
  951.  
  952.   uchar *remap_line=(uchar *)jmalloc(remap_size,"light remap line");
  953.  
  954.   light_patch *f=first;
  955.   uchar *screen_line=screen->scan_line(cy1)+cx1;
  956.  
  957. //    lighting_loop_time=0;
  958.  
  959. //    DiffTime("        PreLite",14); //kill me
  960.     
  961. //    loopnum1 = 0; // kill me
  962.      StartTime(15); //kill me
  963.   for (int y=cy1;y<=cy2;)
  964.   {
  965. //        loopnum1++; // kill me
  966.     int x,count;
  967.     uchar *rem=remap_line;
  968.  
  969.     int todoy=4-((screeny+y)&3);
  970.     if (y+todoy>cy2)
  971.       todoy=cy2-y+1;
  972.  
  973.     int calcy=((y+screeny)&(~3))-cy1;
  974.     
  975. //        StartTime(12);
  976.     if (suffix)
  977.     {
  978.       light_patch *lp=f;
  979.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || 
  980.                   lp->x1>suffix_x || lp->x2<suffix_x);lp=lp->next);
  981.       long caddr=(long)screen_line+cx2-cx1+1-suffix;
  982.       uchar *r=light_lookup+(((long)calc_light_value(lp,suffix_x+screenx,calcy)<<8));
  983.       switch (todoy)
  984.       {
  985.                 case 4 :
  986.                 { 
  987.                   MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;
  988.                 }
  989.                 case 3 :
  990.                 { MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;}
  991.                 case 2 :
  992.                 { MAP_PUT(caddr,(long)r,suffix); caddr+=scr_w;}
  993.                 case 1 :
  994.                 { 
  995.                   MAP_PUT(caddr,(long)r,suffix);
  996.                 }
  997.       }
  998.     }
  999.  
  1000.     if (prefix)
  1001.     {
  1002.       light_patch *lp=f;
  1003.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || 
  1004.                   lp->x1>prefix_x || lp->x2<prefix_x);lp=lp->next);
  1005.  
  1006.       uchar *r=light_lookup+(((long)calc_light_value(lp,prefix_x+screenx,calcy)<<8));
  1007.       long caddr=(long)screen_line;
  1008.       switch (todoy)
  1009.       {
  1010.                 case 4 :
  1011.                 { 
  1012.                   MAP_PUT(caddr,(long)r,prefix); 
  1013.                   caddr+=scr_w; 
  1014.                 }
  1015.                 case 3 :
  1016.                 { MAP_PUT(caddr,(long)r,prefix); caddr+=scr_w; }
  1017.                 case 2 :
  1018.                 { MAP_PUT(caddr,(long)r,prefix); caddr+=scr_w; }
  1019.                 case 1 :
  1020.                 { MAP_PUT(caddr,(long)r,prefix); }
  1021.       }
  1022.       screen_line+=prefix;
  1023.     }
  1024. //        DiffTime("          MAPPUT",16);
  1025.  
  1026.  
  1027. //        loopnum2 = 0; // kill me
  1028. //        StartTime(17); // kill me
  1029.     for (x=prefix,count=0;count<remap_size;count++,x+=8,rem++)    
  1030.     {
  1031. //        loopnum2++; //kill me
  1032.       light_patch *lp=f;
  1033.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || lp->x1>x || lp->x2<x);lp=lp->next);
  1034.       *rem=calc_light_value(lp,x+screenx,calcy);
  1035.     }
  1036.     uchar *addr,*oaddr;
  1037. //         sprintf(kjfie[17],"          Calc   %8d = %2d(%4d)",tmp = DiffTime("",17),loopnum2, tmp/loopnum2);// kill me
  1038.  
  1039. //        StartTime(18); //kill me
  1040.     switch (todoy)
  1041.     {
  1042.       case 4 :    
  1043.       remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
  1044.       case 3 :
  1045.       remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
  1046.       case 2 :
  1047.       remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
  1048.       case 1 :
  1049.       remap_line_asm2(screen_line,light_lookup,remap_line,count);  y++; todoy--;  screen_line+=scr_w;
  1050.     } 
  1051. //        DiffTime("          Remap",18); // kill me
  1052.         
  1053.     screen_line-=prefix;
  1054.  
  1055.   }
  1056.   //     sprintf(kjfie[15],"        Lite     %8d = %2d(%4d)",tmp = DiffTime("",15),loopnum1,tmp/loopnum1);// kill me
  1057.  
  1058.  
  1059.   while (first)
  1060.   {
  1061.     light_patch *p=first;
  1062.     first=first->next;
  1063.     delete p;
  1064.   }
  1065.   jfree(remap_line);
  1066. }
  1067.  
  1068.  
  1069. void double_light_screen(image *sc, long screenx, long screeny, uchar *light_lookup, ushort ambient,
  1070.              image *out, long out_x, long out_y)
  1071. {
  1072.   if (sc->width()*2+out_x>out->width() ||
  1073.       sc->height()*2+out_y>out->height()) 
  1074.     return ;   // screen was resized and small_render has not changed size yet
  1075.  
  1076.  
  1077.   int lx_run,ly_run;                     // light block x & y run size in pixels ==  (1<<lx_run)
  1078.   switch (light_detail) 
  1079.   {
  1080.     case HIGH_DETAIL : 
  1081.     { lx_run=2; ly_run=1; } break;       // 4 x 2 patches
  1082.     case MEDIUM_DETAIL :
  1083.     { lx_run=3; ly_run=2; } break;       // 8 x 4 patches  (default)
  1084.     case LOW_DETAIL :
  1085.     { lx_run=4; ly_run=3; } break;       // 16 x 8 patches
  1086.     case POOR_DETAIL :                   // poor detail is no lighting
  1087.     return ;
  1088.   }
  1089.   if ((int)ambient+ambient_ramp<0)
  1090.     min_light_level=0;
  1091.   else if ((int)ambient+ambient_ramp>63)
  1092.     min_light_level=63;
  1093.   else min_light_level=(int)ambient+ambient_ramp;
  1094.  
  1095.   short cx1,cy1,cx2,cy2;
  1096.   sc->get_clip(cx1,cy1,cx2,cy2);
  1097.  
  1098.  
  1099.   if (ambient==63)      // lights off, just double the pixels
  1100.   {
  1101.     uchar *src=sc->scan_line(0);
  1102.     uchar *dst=out->scan_line(out_y+cy1*2)+cx1*2+out_x;
  1103.     int d_skip=out->width()-sc->width()*2;
  1104.     int x,y;
  1105.     ushort v;
  1106.     for (y=sc->height();y;y--)
  1107.     {
  1108.       for (x=sc->width();x;x--)
  1109.       {
  1110.     v=*(src++);
  1111.     *(dst++)=v;
  1112.     *(dst++)=v;
  1113.       }
  1114.       dst=dst+d_skip;
  1115.       memcpy(dst,dst-out->width(),sc->width()*2);
  1116.       dst+=out->width();
  1117.     }
  1118.  
  1119.     return ;
  1120.   }
  1121.  
  1122.  
  1123.   unsigned char *mint=light_lookup+min_light_level*256;
  1124.  
  1125.   light_patch *first=make_patch_list(cx2-cx1+1,cy2-cy1+1,screenx,screeny);
  1126.  
  1127.  
  1128.   int ytry=(1<<ly_run),xtry=(1<<lx_run);
  1129.   int calcx_mask=(0xefffffff-(xtry-1));
  1130.   int calcy_mask=(0xefffffff-(ytry-1));
  1131.   int scr_w=sc->width();
  1132.   int dscr_w=out->width();
  1133.  
  1134.   int prefix_x=(screenx&7);
  1135.   int prefix=screenx&7;
  1136.   if (prefix)
  1137.     prefix=8-prefix;
  1138.   int suffix_x=cx2-cx1-(screenx&7);
  1139.  
  1140.   int inside_xoff=(screenx+7)&(~7);
  1141.  
  1142.   int suffix=(cx2-cx1-prefix+1)&7;
  1143.  
  1144.  
  1145.   long remap_size=((cx2-cx1+1-prefix-suffix)>>lx_run);
  1146.  
  1147.   uchar *remap_line=(uchar *)jmalloc(remap_size,"light remap line");
  1148.  
  1149.  
  1150.  
  1151.  
  1152.  
  1153.  
  1154.  
  1155.  
  1156.  
  1157.  
  1158.  
  1159.  
  1160.   light_patch *f=first;
  1161.   uchar *in_line=sc->scan_line(cy1)+cx1;
  1162.   uchar *out_line=out->scan_line(cy1*2+out_y)+cx1*2+out_x;
  1163.  
  1164.  
  1165.   for (int y=cy1;y<=cy2;)
  1166.   {
  1167.     int x,count;
  1168. //    while (f->next && f->y2<y) 
  1169. //      f=f->next;
  1170.     uchar *rem=remap_line;
  1171.  
  1172.     int todoy=4-((screeny+y)&3);
  1173.     if (y+todoy>cy2)
  1174.       todoy=cy2-y+1;
  1175.  
  1176.     int calcy=((y+screeny)&(~3))-cy1;
  1177.     
  1178.  
  1179.     if (suffix)
  1180.     {
  1181.       light_patch *lp=f;
  1182.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || 
  1183.                   lp->x1>suffix_x || lp->x2<suffix_x);lp=lp->next);
  1184.       long caddr=(long)in_line+cx2-cx1+1-suffix;
  1185.       long daddr=(long)out_line+(cx2-cx1+1-suffix)*2;
  1186.  
  1187.       uchar *r=light_lookup+(((long)calc_light_value(lp,suffix_x+screenx,calcy)<<8));
  1188.       switch (todoy)
  1189.       {
  1190.     case 4 : 
  1191.     { 
  1192.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
  1193.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
  1194.     }
  1195.     case 3 :
  1196.     { 
  1197.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
  1198.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
  1199.     }
  1200.     case 2 :
  1201.     { 
  1202.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
  1203.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
  1204.     }
  1205.     case 1 :
  1206.     { 
  1207.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w;
  1208.       MAP_2PUT(caddr,daddr,(long)r,suffix); daddr+=dscr_w; caddr+=scr_w;
  1209.     } break;
  1210.       }
  1211.     }
  1212.  
  1213.     if (prefix)
  1214.     {
  1215.       light_patch *lp=f;
  1216.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || 
  1217.                   lp->x1>prefix_x || lp->x2<prefix_x);lp=lp->next);
  1218.  
  1219.       uchar *r=light_lookup+(((long)calc_light_value(lp,prefix_x+screenx,calcy)<<8));
  1220.       long caddr=(long)in_line;
  1221.       long daddr=(long)out_line;
  1222.       switch (todoy)
  1223.       {
  1224.     case 4 :
  1225.     { 
  1226.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
  1227.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
  1228.     }
  1229.     case 3 :
  1230.     { 
  1231.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
  1232.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
  1233.     }
  1234.     case 2 :
  1235.     { 
  1236.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
  1237.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
  1238.     }
  1239.     case 1 :
  1240.     { 
  1241.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w;
  1242.       MAP_2PUT(caddr,daddr,(long)r,prefix); daddr+=dscr_w; caddr+=scr_w;
  1243.     } break;
  1244.       }
  1245.       in_line+=prefix;
  1246.       out_line+=prefix*2;
  1247.     }
  1248.  
  1249.  
  1250.  
  1251.  
  1252.     for (x=prefix,count=0;count<remap_size;count++,x+=8,rem++)    
  1253.     {
  1254.       light_patch *lp=f;
  1255.       for (;(lp->y1>y-cy1 || lp->y2<y-cy1 || lp->x1>x || lp->x2<x);lp=lp->next);
  1256.       *rem=calc_light_value(lp,x+screenx,calcy);
  1257.     }
  1258.  
  1259.     rem=remap_line;
  1260.  
  1261.     put_8line(in_line,out_line,rem,light_lookup,count); 
  1262.     memcpy(out_line+dscr_w,out_line,count*16);
  1263.     out_line+=dscr_w;
  1264.     in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
  1265.     if (todoy)
  1266.     {
  1267.       put_8line(in_line,out_line,rem,light_lookup,count); 
  1268.       memcpy(out_line+dscr_w,out_line,count*16);
  1269.       out_line+=dscr_w;
  1270.       in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
  1271.       if (todoy)
  1272.       {
  1273.     put_8line(in_line,out_line,rem,light_lookup,count); 
  1274.     memcpy(out_line+dscr_w,out_line,count*16);
  1275.     out_line+=dscr_w;
  1276.     in_line+=scr_w; out_line+=dscr_w; y++; todoy--;
  1277.     if (todoy)
  1278.     {
  1279.       put_8line(in_line,out_line,rem,light_lookup,count); 
  1280.       memcpy(out_line+dscr_w,out_line,count*16);
  1281.       out_line+=dscr_w;
  1282.       in_line+=scr_w; out_line+=dscr_w; y++;
  1283.     }
  1284.       }
  1285.     }      
  1286.     in_line-=prefix;
  1287.     out_line-=prefix*2;
  1288.   } 
  1289.  
  1290.  
  1291.   while (first)
  1292.   {
  1293.     light_patch *p=first;
  1294.     first=first->next;
  1295.     delete p;
  1296.   }
  1297.   jfree(remap_line);
  1298. }
  1299.  
  1300.  
  1301.  
  1302.  
  1303. void add_light_spec(spec_directory *sd, char *level_name)
  1304. {
  1305.   long size=4+4;  // number of lights and minimum light levels
  1306.   for (light_source *f=first_light_source;f;f=f->next)
  1307.     size+=6*4+1;
  1308.   sd->add_by_hand(new spec_entry(SPEC_LIGHT_LIST,"lights",NULL,size,0));  
  1309. }
  1310.  
  1311. void write_lights(bFILE *fp)
  1312. {
  1313.   int t=0;
  1314.   light_source *f=first_light_source;
  1315.   for (;f;f=f->next) t++;
  1316.   fp->write_long(t);
  1317.   fp->write_long(min_light_level);
  1318.   for (f=first_light_source;f;f=f->next)
  1319.   {
  1320.     fp->write_long(f->x);
  1321.     fp->write_long(f->y);
  1322.     fp->write_long(f->xshift);
  1323.     fp->write_long(f->yshift);
  1324.     fp->write_long(f->inner_radius);
  1325.     fp->write_long(f->outer_radius);
  1326.     fp->write_byte(f->type);
  1327.   }
  1328. }
  1329.  
  1330.  
  1331. void read_lights(spec_directory *sd, bFILE *fp, char *level_name)
  1332. {
  1333.   delete_all_lights();
  1334.   spec_entry *se=sd->find("lights");
  1335.   if (se)
  1336.   {
  1337.     fp->seek(se->offset,SEEK_SET);
  1338.     long t=fp->read_long();
  1339.     min_light_level=fp->read_long();
  1340.     light_source *last;
  1341.     while (t)
  1342.     {
  1343.       t--;
  1344.       long x=fp->read_long();
  1345.       long y=fp->read_long();
  1346.       long xshift=fp->read_long();
  1347.       long yshift=fp->read_long();
  1348.       long ir=fp->read_long();
  1349.       long ora=fp->read_long();
  1350.       long ty=fp->read_byte();
  1351.  
  1352.       light_source *p=new light_source(ty,x,y,ir,ora,xshift,yshift,NULL);
  1353.       
  1354.       if (first_light_source)
  1355.         last->next=p;
  1356.       else first_light_source=p;
  1357.       last=p;
  1358.     }
  1359.   }
  1360. }
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.